package org.eclipse.mylyn.rememberthemilk.core;

import java.io.File;
import java.util.Set;

import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.mylyn.rememberthemilk.core.RTMAttributeMapper.Attribute;
import org.eclipse.mylyn.rememberthemilk.core.client.RTMClient;
import org.eclipse.mylyn.rememberthemilk.core.client.RTMClientManager;
import org.eclipse.mylyn.rememberthemilk.core.model.RTMSearch;
import org.eclipse.mylyn.tasks.core.AbstractRepositoryConnector;
import org.eclipse.mylyn.tasks.core.IRepositoryQuery;
import org.eclipse.mylyn.tasks.core.ITask;
import org.eclipse.mylyn.tasks.core.ITaskMapping;
import org.eclipse.mylyn.tasks.core.RepositoryStatus;
import org.eclipse.mylyn.tasks.core.TaskRepository;
import org.eclipse.mylyn.tasks.core.data.AbstractTaskDataHandler;
import org.eclipse.mylyn.tasks.core.data.TaskData;
import org.eclipse.mylyn.tasks.core.data.TaskDataCollector;
import org.eclipse.mylyn.tasks.core.data.TaskMapper;
import org.eclipse.mylyn.tasks.core.sync.ISynchronizationSession;

import com.mdt.rtm.data.RtmTaskList;
import com.mdt.rtm.data.RtmTaskSeries;
import com.mdt.rtm.data.RtmTasks;

public class RTMRepositoryConnector extends AbstractRepositoryConnector {
	private final static String CLIENT_LABEL = "Remember The Milk";

	private RTMTaskDataHandler taskDataHandler = null;
	private RTMClientManager clientManager;

	public RTMRepositoryConnector() {
		RTMCorePlugin.getDefault().setConnector(this);
		taskDataHandler = new RTMTaskDataHandler(this);
	}

	@Override
	public boolean canCreateNewTask(TaskRepository arg0) {
		return true;
	}

	@Override
	public boolean canCreateTaskFromKey(TaskRepository arg0) {
		// TODO Auto-generated method stub
		return false;
	}

	// TODO: createTaskMapper this guy maybe
	// public AbstractTask createTask(String repositoryUrl, String id, String
	// summary) {
	// RTMTask rtmTask = new RTMTask(repositoryUrl, id, summary);
	// rtmTask.setCreationDate(new Date());
	// return rtmTask;
	// }

	// @Override
	// public AbstractTaskAttachmentHandler getAttachmentHandler() {
	// // TODO Auto-generated method stub
	// return null;
	// }

	@Override
	public String getLabel() {
		return CLIENT_LABEL;
	}

	@Override
	public String getConnectorKind() {
		return RTMCorePlugin.REPOSITORY_KIND;
	}

	@Override
	public String getRepositoryUrlFromTaskUrl(String arg0) {
		// TODO Auto-generated method stub
		return null;
	}

	// @Override
	// public AbstractTaskDataHandler getTaskDataHandler() {
	// if(taskDataHandler==null)
	// {
	// taskDataHandler = new RTMTaskDataHandler(this);
	// }
	// return taskDataHandler;
	// }

	@Override
	public String getTaskIdFromTaskUrl(String arg0) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public String getTaskUrl(String arg0, String arg1) {
		// TODO Auto-generated method stub
		return null;
	}

	// public boolean markStaleTasks(TaskRepository repository,
	// Set<AbstractTask> tasks,
	// IProgressMonitor monitor) throws CoreException {
	@Override
	public void preSynchronization(ISynchronizationSession event, IProgressMonitor monitor) throws CoreException {
		try {
			monitor.beginTask("Getting changed tasks", IProgressMonitor.UNKNOWN);

			TaskRepository repository = event.getTaskRepository();
			Set<ITask> tasks = event.getTasks();
			if (repository.getSynchronizationTimeStamp() == null
					|| repository.getSynchronizationTimeStamp().length() == 0) {
				for (ITask task : tasks) {
					// task.setStale(true);
					event.markStale(task);
				}
				return;
			}

			/*
			 * Date since = new Date(0); try { since =
			 * TracUtils.parseDate(Integer
			 * .parseInt(repository.getSynchronizationTimeStamp())); } catch
			 * (NumberFormatException e) { }
			 */

			try {
				RTMClient client = getClientManager().getRepository(repository);
				// Set<Integer> ids =
				// client.getRTMTasks("status:completed OR status:incomplete");
				// Set<Integer> ids = client.getChangedTickets(since);
				/*
				 * if (ids.isEmpty()) { // repository is unchanged return false;
				 * }
				 * 
				 * if (ids.size() == 1) { // getChangedTickets() is expected to
				 * always return at least one ticket because // the repository
				 * synchronization timestamp is set to the most recent
				 * modification date Integer id = ids.iterator().next(); Date
				 * lastChanged = client.getTicketLastChanged(id); if
				 * (since.equals(lastChanged)) { // repository didn't actually
				 * change return false; } }
				 */

				for (ITask task : tasks) {
					// Integer id = getTicketId(task.getTaskId());
					// if (ids.contains(id)) {
					event.markStale(task);
					// }
				}

				return;
			} catch (Exception e) {
				throw new CoreException(RTMCorePlugin.toStatus(e, repository));
			}
		} finally {
			monitor.done();
		}
	}

	@Override
	public IStatus performQuery(TaskRepository repository, IRepositoryQuery query, TaskDataCollector collector,
			ISynchronizationSession session, IProgressMonitor monitor) {

		RTMClient rtmClient;
		RtmTasks tasks;
		query.getUrl();
		try {
			rtmClient = getClientManager().getRepository(repository);
			tasks = rtmClient.getRTMTasks(query.getUrl());

			for (RtmTaskList taskList : tasks.getLists()) {
				for (RtmTaskSeries serie : taskList.getSeries()) {
					// TODO: Going to need to create a TaskData and do the whole
					// mapping thing
					TaskData data = taskDataHandler.createTaskDataFromSeries(serie, repository);
					collector.accept(data);
				}
			}
		} catch (Throwable e) {
			return RTMCorePlugin.toStatus(e, repository);
		}

		return Status.OK_STATUS;
	}

	/**
	 * Updates fields of <code>task</code> from <code>ticket</code>.
	 */
	// TODO: this guy does the stuff which would probably be done my the mapper
	// public void updateTaskFromTicket(TaskRepository repository, RTMTask task,
	// RtmTaskSeries serie, boolean notify) {
	// RtmTask rtmtask = serie.getTask();
	// if (serie.getName() != null) {
	// task.setSummary(serie.getName());
	// }
	// task.setCompleted( (rtmtask.getCompleted()!=null) );
	//		
	// task.setPriority( RTMTask.getMylynPriority(rtmtask.getPriority()));
	//		
	// task.setDueDate(rtmtask.getDue());
	//				
	// //task.setTaskKind(kind);
	//		
	// if (serie.getCreated() != null) {
	// task.setCreationDate(serie.getCreated());
	// }
	//		
	// //http://www.rememberthemilk.com/home/ceesbos/
	// task.setUrl("http://www.rememberthemilk.com/home/" +
	// repository.getUserName() +"/" + serie.getListId() + "/" +
	// rtmtask.getId());
	//
	// if (notify) {
	// taskList.notifyTaskChanged(task, false);
	// }
	// }
	public void updateAttributes(TaskRepository repository, IProgressMonitor monitor) throws CoreException {
		try {
			RTMClient client = getClientManager().getRepository(repository);
			client.updateAttributes(true);
		} catch (Exception e) {
			throw new CoreException(RepositoryStatus.createStatus(repository.getUrl(), IStatus.WARNING,
					RTMCorePlugin.PLUGIN_ID, "Could not update attributes"));
		}

	}
	
	// @Override
	// public void updateTaskFromRepository(TaskRepository repository,
	// AbstractTask repositoryTask,
	// IProgressMonitor monitor) throws CoreException {
	// if (repositoryTask instanceof RTMTask) {
	// try {
	// RTMClient client = getClientManager().getRepository(repository);
	// RtmTaskSeries serie = client.getRTMTaskSerie(repositoryTask.getTaskId());
	// updateTaskFromTicket(repository, (RTMTask) repositoryTask, serie, false);
	// } catch (Exception e) {
	// throw new CoreException(RTMCorePlugin.toStatus(e, repository));
	// }
	// }
	// }
	//
	// @Override
	// public void updateTaskFromTaskData(TaskRepository taskRepository,
	// AbstractTask repositoryTask,
	// TaskData taskData ) {
	// if (taskData != null) {
	// repositoryTask.setSummary(taskData.getSummary());
	//			
	// }
	//		
	// }

	public synchronized RTMClientManager getClientManager() {
		if (clientManager == null) {
			File cacheFile = null;
			if (RTMCorePlugin.getDefault().getRepostioryAttributeCachePath() != null) {
				cacheFile = RTMCorePlugin.getDefault().getRepostioryAttributeCachePath().toFile();
			}
			clientManager = new RTMClientManager(cacheFile);
		}
		return clientManager;
	}

	public void stop() {
		if (clientManager != null) {
			clientManager.writeCache();
		}
	}

	@Override
	public boolean hasLocalCompletionState(TaskRepository taskRepository, ITask task) {
		// TODO isLocal returned true. i don't think this is right
		return super.hasLocalCompletionState(taskRepository, task);
	}

	@Override
	public TaskData getTaskData(TaskRepository taskRepository, String taskId, IProgressMonitor monitor)
			throws CoreException {
		RTMClient rtmClient;
		TaskData data = null;
		try {
			rtmClient = getClientManager().getRepository(taskRepository);
			RtmTaskSeries series = rtmClient.getRTMTaskSerie(taskId);

			data = taskDataHandler.createTaskDataFromSeries(series, taskRepository);
		
		
		} catch (Throwable e) {
			e.printStackTrace();
		}

		return data;
	}

	@Override
	public boolean hasTaskChanged(TaskRepository taskRepository, ITask task, TaskData taskData) {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public void updateRepositoryConfiguration(TaskRepository taskRepository, IProgressMonitor monitor)
			throws CoreException {
		// TODO Auto-generated method stub

	}
	
	@Override
	public TaskMapper getTaskMapping(TaskData taskData) {
		// TODO Auto-generated method stub
		return (TaskMapper) super.getTaskMapping(taskData);
	}

	@Override
	public void updateTaskFromTaskData(TaskRepository taskRepository, ITask task, TaskData taskData) {
		TaskMapper mapper = getTaskMapping(taskData);
		mapper.applyTo(task);
	}

	@Override
	public AbstractTaskDataHandler getTaskDataHandler() {
		return taskDataHandler;
	}
}
